package com.sxjh.controller.ny;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.cglib.CglibUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sxjh.annotation.UserLog;
import com.sxjh.common.BaseController;
import com.sxjh.common.Constant;
import com.sxjh.common.Result;
import com.sxjh.common.ZPage;
import com.sxjh.config.Authorization;
import com.sxjh.entity.*;
import com.sxjh.entity.param.PlannedOrderListParam;
import com.sxjh.entity.param.TaskAddParam;
import com.sxjh.entity.param.TaskRectifyParam;
import com.sxjh.entity.param.TaskSkipParam;
import com.sxjh.entity.result.TaskList2Result;
import com.sxjh.entity.result.TaskListResult;
import com.sxjh.entity.result.TaskOneResult;
import com.sxjh.enums.TaskStatusEnum;
import com.sxjh.service.*;
import com.sxjh.uitl.LocalDateTimeUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 派车单  前端控制器
 * insert into permissions
 * (name, guard_name, description) values
 * ('task.list', 'api', '派车单 列表'),
 * ('task.query', 'api', '派车单 查询'),
 * ('task.add', 'api', '派车单 增加'),
 * ('task.del', 'api', '派车单 删除'),
 * ('task.update', 'api', '派车单 修改'),
 * </p>
 *
 * @author zixin
 * @since 2021-06-06
 */
@Slf4j
@RestController
@RequestMapping("/task")
@Api(tags = "派车单")
public class TaskController extends BaseController {

    @Autowired
    private IcService icService;

    @Autowired
    private TaskService taskService;

    @Autowired
    private MateriaLoadService materiaLoadService;

    @Autowired
    private MateriaUnloadService materiaUnloadService;

    @Autowired
    private WagonNumberService wagonNumberService;

    @Autowired
    private PlannedOrdersService plannedOrdersService;

    @Autowired
    private GoodsLocationService goodsLocationService;

    @Autowired
    private HttpServletRequest request;

    @Autowired
    private FactoryService factoryService;

    @Autowired
    private UserService userService;

    @ApiOperation("列表")
    @GetMapping
    @Authorization("task.list")
    Result<ZPage<TaskListResult>> list(TaskListResult param) {
        IPage iPage = new Page(param.getCurrent(), param.getSize());
        if (param.getSize() == -1) {
            iPage.setSize(Constant.maxSize);
        }
        Integer id = getUserInfo(request);
        //根据用户id获取所有角色
        Set<String> roleIds = userService.roles(id);
        if (CollUtil.isEmpty(roleIds)) {
            return Result.ok(null);
        }

        //查询所有的工厂配置
        List<FactoryEntity> factoryList = factoryService.list();
        if (CollUtil.isNotEmpty(factoryList)) {
            List<Integer> upFactoryIdList = Lists.newArrayList();
            roleIds.forEach(r -> {
                //用户所属的角色是否在工厂配置中
                List<Integer> factoryIdList = factoryList.stream().filter(f -> {
                    String roleId = f.getRoleId();
                    if (StrUtil.isBlank(roleId)) return false;
                    List<String> roleId1s = Arrays.asList(roleId.split(","));
                    return roleId1s.contains(r);
                }).map(BaseEntity::getId).distinct().collect(Collectors.toList());
                if (CollUtil.isNotEmpty(factoryIdList)) {
                    upFactoryIdList.addAll(factoryIdList);
                }
            });
            if (CollUtil.isNotEmpty(upFactoryIdList)) {
                //去重
                Set<Integer> set = new HashSet<Integer>(upFactoryIdList);
                //log.info("====派车单分页查询用户id:{},,,角色id:{},,,工厂id:{}", id, JSONUtil.toJsonStr(roleIds), JSONUtil.toJsonStr(set));
                param.setUpFactoryIdList(set);
            }
        }
        iPage = taskService.list(iPage, param);
        ZPage<TaskListResult> zPage = copyPage(iPage, TaskListResult::new);
        return Result.ok(zPage);
    }

    @ApiOperation("查询详情")
    @GetMapping("/{id}")
    @Authorization("task.list")
    Result<TaskOneResult> query(@PathVariable Integer id) {
        Task task = taskService.getById(id);
        if (task == null) return Result.err("没有该ID信息");
        TaskOneResult one = CglibUtil.copy(task, TaskOneResult.class);
        return Result.ok(one);
    }

    @ApiOperation("新增派车单")
    @PostMapping
    @Authorization("task.add")
    @UserLog(desc = "内部倒运-新增派车单管理", roleCode = "task.add")
    Result<String> add(@RequestBody @Validated TaskAddParam param) {
        WagonNumber wagonNumber = wagonNumberService.getById(param.getWagonNumberId());
        if (Objects.isNull(wagonNumber)) {
            return Result.err("该车辆信息不存在");
        }
        if (wagonNumber.getDriverId() == null || wagonNumber.getDriverId() == 0) {
            return Result.err("该车辆未绑定司机");
        }
        //司机必须绑定ic卡校验
        LambdaQueryWrapper<Ic> queryIc = new LambdaQueryWrapper<>();
        queryIc.eq(Ic::getWagonNumberId, param.getWagonNumberId());
        List<Ic> ic = icService.list(queryIc);
        if (CollUtil.isEmpty(ic)) {
            return Result.err("该司机尚未绑定IC卡");
        }
        //查询计划单信息
        PlannedOrderListParam plannedOrderListParam = new PlannedOrderListParam();
        plannedOrderListParam.setId(param.getPlannedOrderId());
        IPage<PlannedOrderListParam> aPage = plannedOrdersService.queryPage(new Page<>(1, 10), plannedOrderListParam);
        if (aPage != null && CollUtil.isNotEmpty(aPage.getRecords())) {
            plannedOrderListParam = aPage.getRecords().get(0);
            LocalDateTime startDate = DateUtil.parseLocalDateTime(plannedOrderListParam.getStartDate());
            LocalDateTime endDate = DateUtil.parseLocalDateTime(plannedOrderListParam.getEndDate());

            LocalDateTime startDate1 = param.getStartDate();
            LocalDateTime endDate1 = param.getEndDate();
            if (startDate1.isBefore(startDate) || endDate1.isAfter(endDate)) {
                return Result.err("派车单起止时间不在计划单起止时间范围内");
            }
        }

        List<Task> taskList = Lists.newArrayList();
        for (int i = 0; i < param.getCount(); i++) {
            Task task = convert(plannedOrderListParam);
            task.setWagonNumberId(param.getWagonNumberId());
            task.setStartDate(param.getStartDate());
            task.setEndDate(param.getEndDate());
            taskList.add(task);
        }
        try {
            taskService.saveBatch(taskList);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            return Result.err("添加失败,该车号派车单已存在或其他异常");
        }
        return Result.ok("success");
    }

    @ApiOperation("删除")
    @GetMapping("/delete/{id}")
    @Authorization("task.del")
    @UserLog(desc = "内部倒运-删除派车单管理", roleCode = "task.del")
    Result<String> del(@PathVariable Integer id) {
        Task task = taskService.getById(id);
        if (Objects.nonNull(task) && task.getStatus() != 1) {
            return err("派车单已在执行中不能删除!");
        }
        /*String record = "";
        if (task != null) {
            WagonNumber wagonNumber = wagonNumberService.getById(task.getWagonNumberId());
            record = String.format("车牌号：%s", wagonNumber == null ? "" : wagonNumber.getNumber());
        }*/
        return taskService.removeById(id) ? Result.ok("success") : Result.err("删除失败,此ID不存在或其他异常");
    }

    @ApiOperation("修改")
    @PostMapping("/update/{id}")
    @Authorization("task.update")
    @UserLog(desc = "内部倒运-修改派车单管理", roleCode = "task.update")
    Result<String> update(@PathVariable Integer id, @RequestBody @Validated TaskAddParam param) {
        param.setId(id);
        Task task = CglibUtil.copy(param, Task.class);
        try {
            boolean isU = taskService.updateById(task);
            if (!isU) return Result.err("此ID不存在或其他异常");
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            return Result.err("修改失败：车号已有派车单或其他异常");
        }
        WagonNumber wagonNumber = wagonNumberService.getById(task.getWagonNumberId());
        String record = String.format("车牌号：%s", wagonNumber == null ? "" : wagonNumber.getNumber());
        return Result.ok(record);
    }

    @ApiOperation("初磅作废")
    @GetMapping(value = "/invalid0")
    //@UserLog(desc = "内部倒运-初磅作废", roleCode = "task.update")
    public Result<Object> invalid0(@RequestParam("id") Integer id) {
        Task task = taskService.getById(id);
        /*if (Objects.nonNull(task) && task.getStatus() == 1) {
            return err("派车单尚未执行，无需作废!");
        }*/
        task.setStatus(TaskStatusEnum.ONE.getValue());
        //task.setInvalidAt(LocalDateTimeUtil.getTime());
        taskService.updateTaskById(task);
        return Result.ok(HttpStatus.OK);
    }

    @ApiOperation("作废")
    @GetMapping(value = "/invalid")
    @UserLog(desc = "内部倒运-作废派车单管理", roleCode = "task.update")
    public Result<Object> invalid(@RequestParam("id") Integer id) {
        Task task = taskService.getById(id);
        /*if (Objects.nonNull(task) && task.getStatus() == 1) {
            return err("派车单尚未执行，无需作废!");
        }*/
        task.setStatus(TaskStatusEnum.FOUR.getValue());
        task.setInvalidAt(LocalDateTimeUtil.getTime());
        taskService.updateById(task);
        return Result.ok(HttpStatus.OK);
    }

    @ApiOperation("派车单列表")
    @GetMapping("taskList")
    Result<ZPage<TaskList2Result>> taskList(TaskListResult param) {
        IPage iPage = new Page(param.getCurrent(), param.getSize());
        if (param.getSize() == -1) {
            iPage.setSize(Constant.maxSize);
        }
        iPage = taskService.list(iPage, param);
        ZPage<TaskList2Result> zPage = copyPage(iPage, TaskList2Result::new);
        return Result.ok(zPage);
    }

    @ApiOperation("派车单矫正")
    @PostMapping(value = "/rectify")
    @UserLog(desc = "内部倒运-矫正派车单管理", roleCode = "task.update")
    public Result<Object> rectify(@RequestBody TaskRectifyParam param) {
        //TODO 重新建立正确的派车单、初称过磅信息和回称过磅信息的关联关系,原来的错误的派车单信息、初称和回称过磅信息自动作废，作废后的派车单恢复为“未执行”状态
        Task task = taskService.getById(param.getId());
        Integer newId = param.getNewId();
        if (newId == task.getId()) return err("矫正单号不能和原单号一样, 请重新选择");
        Task newTask = taskService.getById(newId);

        // 变更矫正信息
        if (newTask != null) {
            //只覆盖 过磅的重量，过磅的图片及过磅的时间信息
            newTask.setTare(task.getTare());
            newTask.setTareAt(task.getTareAt());
            newTask.setTareImg(task.getTareImg());
            newTask.setTareImgTwo(task.getTareImgTwo());

            newTask.setGross(task.getGross());
            newTask.setGrossAt(task.getGrossAt());
            newTask.setGrossImg(task.getGrossImg());
            newTask.setGrossImgTwo(task.getGrossImgTwo());

            newTask.setUpIsSkip(task.getUpIsSkip());
            newTask.setUpImg(task.getUpImg());
            newTask.setUpImgTwo(task.getUpImgTwo());
            newTask.setDownIsSkip(task.getDownIsSkip());
            newTask.setDownImg(task.getDownImg());
            newTask.setDownImgTwo(task.getDownImgTwo());

            newTask.setCurrNode(task.getCurrNode());
            newTask.setStatus(task.getStatus());
            newTask.setStartDate(task.getStartDate());
            newTask.setEndDate(task.getEndDate());
            newTask.setCreatedBy(task.getCreatedBy());
            newTask.setCreatedAt(task.getCreatedAt());
            newTask.setUpdatedBy(task.getUpdatedBy());
            newTask.setUpdatedAt(task.getUpdatedAt());
            taskService.updateById(newTask);
        }

        // 变更旧车单矫正状态
        if (task != null) {
            taskService.updateTaskById(task);
        }
        return Result.ok(HttpStatus.OK);
    }

    @ApiOperation("查询派车单号列表")
    @GetMapping(value = "/queryOrderNoList")
    public Result<List<Task>> queryOrderNoList(@RequestParam("orderNo") String orderNo,
                                               @RequestParam(value = "likeOrderNo", required = false) String likeOrderNo) {
        LambdaQueryWrapper<Task> query = new LambdaQueryWrapper<Task>().eq(Task::getStatus, 1).ne(Task::getOrderNo, orderNo);
        if (StrUtil.isNotBlank(likeOrderNo)) {
            query.like(Task::getOrderNo, likeOrderNo);
        }
        List<Task> tasks = taskService.list(query);
        return Result.ok(tasks);
    }


    @ApiOperation("跳过")
    @GetMapping(value = "/skip")
    @UserLog(desc = "内部倒运-跳过派车单管理", roleCode = "task.update")
    public Result<Object> skip(TaskSkipParam param) {
        //TODO 装卸点拍照、卸车单刷卡确认环节才可以跳过
        Task task = taskService.getById(param.getId());
        Integer currNode = task.getCurrNode();
        if (Objects.nonNull(task)) {
            if (currNode != null && currNode == 1) {
                task.setUpIsSkip(1);
                task.setCurrNode(2);
                task.setStatus(2);
            } else if (currNode != null && currNode == 3) {
                GoodsLocation goodsDownLocation = goodsLocationService.getById(task.getUnloadId());
                int downPhotoFlag = goodsDownLocation.getPhotoFlag();
                int downConfirmFlag = goodsDownLocation.getConfirmFlag();
                if (downPhotoFlag == 1 && downConfirmFlag == 1) {
                    //不需要拍照，不需要签字，没有下一节点
                    //task.setStatus(3);
                } else if (downPhotoFlag == -1 && downConfirmFlag == -1) {
                    //需要拍照，需要签字
                    task.setDownIsSkip(1);
                    task.setCurrNode(4);
                    task.setStatus(2);
                } else if (downPhotoFlag == 1 && downConfirmFlag == -1) {
                    //不需要拍照，需要签字
                    task.setDownIsSkip(1);
                    task.setCurrNode(5);
                    task.setStatus(3);
                } else {
                    //需要拍照，不需要签字
                    task.setDownIsSkip(1);
                    task.setCurrNode(4);
                    task.setStatus(3);
                }
            } else if (currNode != null && currNode == 4) {
                GoodsLocation goodsDownLocation = goodsLocationService.getById(task.getUnloadId());
                if (1 == goodsDownLocation.getConfirmFlag()) {
                    //不需要签字

                } else {
                    //不需要拍照，需要签字
                    task.setDownIsSkip(1);
                    task.setCurrNode(5);
                    task.setStatus(3);
                }
            } else {
                task.setUpIsSkip(2);
                task.setDownIsSkip(2);
            }
            taskService.updateById(task);

            // 如果节点是5，更新状态变成完成。
            /*Task nodeTask = taskService.getById(param.getId());
            Integer taskCurrNode = nodeTask.getCurrNode();
            if (taskCurrNode != null && taskCurrNode == 5) {
                nodeTask.setStatus(3);
                taskService.updateById(nodeTask);
            }*/
        }
        return Result.ok(HttpStatus.OK);
    }

    private Task convert(PlannedOrderListParam plannedOrderListParam) {
        Task task = new Task();
        String orderNo = "DY" + DateUtil.format(DateUtil.date(), "yyyyMMddHHmmssSSS") + RandomUtil.randomNumbers(4);
        task.setOrderNo(orderNo);
        task.setPlannedOrderId(plannedOrderListParam.getId());
        task.setPlannedOrderNo(plannedOrderListParam.getOrderNo());
        //task.setWagonNumberId(plannedOrderListParam.get);
        task.setMaterialId(plannedOrderListParam.getMaterialId());
        task.setLoadId(plannedOrderListParam.getLocationUpId());
        task.setUnloadId(plannedOrderListParam.getLocationDownId());
        //task.setTare(String tare) ;
        //task.setTareImg(String tareImg);
        //task.setTareImgTwo(String tareImgTwo) ;
        //task.setTareAt(LocalDateTime tareAt);
        //task.setGross(String gross);
        //task.setGrossImg(String grossImg) ;
        //task.setGrossImgTwo(String grossImgTwo) ;
        //task.setGrossAt(LocalDateTime grossAt) ;
        //task.setUpImg(String upImg) ;
        //task.setUpImgTwo(String upImgTwo);
        //task.setDownImg(String downImg) ;
        //task.setDownImgTwo(String downImgTwo);
        //task.setCurrNode();
        task.setStatus(TaskStatusEnum.ONE.getValue());
        //task.setCreatedBy(Integer createdBy) ;
        //task.setCreatedAt(LocalDateTime createdAt);
        //task.setUpdatedBy(Integer updatedBy);
        //task.setUpdatedAt(LocalDateTime updatedAt);
        //task.setDeletedBy(Integer deletedBy);
        //task.setDeletedAt(LocalDateTime deletedAt);
        return task;
    }

}